﻿/**
 *       Project: ServerLib
 *     Copyright: Copyright (C) 2008, Rob Kennedy
 *   Create Date: 2008-14-07 4:43 PM
 * Modified Date: 2008-14-07 4:43 PM    RK  Added comments
 *      Comments: Ignore SA1633.
 *      
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

namespace ServerLib.Core
{
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Collections;
    using System.Collections.Specialized;

    /// --------------------------------------------------------------------
    /// Project	 : ServerLib
    /// Class	 : Types
    /// Inherits : N/A
    /// --------------------------------------------------------------------
    /// <summary>
    /// Contains methods that provide type and data validation
    /// routines; type conversions; collection copying; etc.
    /// </summary>
    /// <authorname>Rob Kennedy</authorname>
    /// <remarks>
    /// </remarks>
    /// --------------------------------------------------------------------
    public class Types
    {
        #region Public Methods
        /// <summary>
        /// Copies a collection of objects/values to another collection
        /// </summary>
        /// <typeparam name="T">Type of the source and destination collection items</typeparam>
        /// <param name="source">The source collection to copy from</param>
        /// <param name="destination">The destination collection to copy to</param>
        public static void CopyCollection<T>(ICollection<T> source, ICollection<T> destination)
        {
            destination.Clear();
            foreach (T local in source)
            {
                destination.Add(local);
            }
        }

        /// <summary>
        /// Copies a Dictionary collection of objects/values to another Dictionary collection
        /// </summary>
        /// <typeparam name="T">Type of source collection items</typeparam>
        /// <typeparam name="S">Type of destination collection items</typeparam>
        /// <param name="source">The source dictionary collection to copy from</param>
        /// <param name="destination">The destination dictionary collection to copy to</param>
        public static void CopyCollection<T, S>(IDictionary<T, S> source, IDictionary<T, S> destination)
        {
            destination.Clear();
            foreach (T local in source.Keys)
            {
                destination.Add(local, source[local]);
            }
        }
        
        /// <summary>
        /// Copies a NameValueCollection of NameValuePairs to another NameValueCollection
        /// </summary>
        /// <param name="source">The source NameValueCollection to copy from</param>
        /// <param name="destination">The destination NameValueCollection to copy to</param>
        public static void CopyCollection(NameValueCollection source, NameValueCollection destination)
        {
            destination.Clear();
            foreach (string str in source.Keys)
            {
                destination.Add(str, source[str]);
            }
        }

        /// <summary>
        ///  Joins an array of integers into a delimited string
        /// </summary>
        /// <param name="separator">The separator to delimit the string values</param>
        /// <param name="intArray">The array of integer values</param>
        /// <returns>A delimited string of number values</returns>
        public static string JoinIntArray(string separator, int[] intArray)
        {
            string resultValue = string.Empty;
            
            if (intArray == null ? intArray.Length > 0 : false)
            {
                StringBuilder builder = new StringBuilder();

                for (int i = 0; i < intArray.Length; i++)
                {
                    if (i != 0)
                    {
                        builder.Append(separator);
                    }

                    builder.Append(intArray[i]);
                }

                resultValue = builder.ToString();
            }
            
            return resultValue;
        }

        /// <summary>
        ///  Splits a delimited string of values into an array
        /// </summary>
        /// <param name="separator">The dilimiter to parse</param>
        /// <param name="delimitedString">A dilimited string to split into an array of values</param>
        /// <returns>An array of values parsed from the passed delimited string</returns>
        public static Array SplitIntArray(char separator, string delimitedString)
        {
            Array resultValue = null;

            if (!IsNullorEmpty(delimitedString))
            {
                string[] values = delimitedString.Split(separator);
                ArrayList al = new ArrayList();
                
                foreach (string value in values)
                {
                    al.Add(FixInteger(value));
                }

                resultValue = al.ToArray(typeof(int));
            }

            return resultValue;
        }

        /// <summary>
        /// Determines if a passed value is null or DBNull
        /// </summary>
        /// <param name="value">The value to check</param>
        /// <returns>Returns true if value passed is null or DBNull</returns>
        public static bool IsNullorDBNull(object value)
        {
            return value == null || value == DBNull.Value;
        }

        /// <summary>
        /// Determines if the string passed is null or empty
        /// </summary>
        /// <param name="value">the value to check</param>
        /// <returns>Returns true if the value is null or empty</returns>
        public static bool IsNullorDBNull(string value)
        {
            return IsNullorEmpty(value);
        }

        /// <summary>
        /// Determines if a passed value is null or DBNull
        /// </summary>
        /// <param name="value">The value to check</param>
        /// <returns>Returns true if value passed is null or DBNull</returns>
        public static bool IsNullorDBNull(int value)
        {
            return IsNullorDBNull((object)value);
        }

        /// <summary>
        /// Determines if a passed value is null or DBNull
        /// </summary>
        /// <param name="value">The value to check</param>
        /// <returns>Returns true if value passed is null or DBNull</returns>
        public static bool IsNullorDBNull(long value)
        {
            return IsNullorDBNull((object)value);
        }

        /// <summary>
        /// Determines if a passed value is null or DBNull
        /// </summary>
        /// <param name="value">The value to check</param>
        /// <returns>Returns true if value passed is null or DBNull</returns>
        public static bool IsNullorDBNull(double value)
        {
            return IsNullorDBNull((object)value);
        }

        /// <summary>
        /// Determines if a passed value is null or DBNull
        /// </summary>
        /// <param name="value">The value to check</param>
        /// <returns>Returns true if value passed is null or DBNull</returns>
        public static bool IsNullorDBNull(decimal value)
        {
            return IsNullorDBNull((object)value);
        }

        /// <summary>
        /// Determines if a passed value is null or DBNull
        /// </summary>
        /// <param name="value">The value to check</param>
        /// <returns>Returns true if value passed is null or DBNull</returns>
        public static bool IsNullorDBNull(DateTime value)
        {
            return IsNullorDBNull((object)value);
        }

        /// <summary>
        /// Determines if a passed value is null or DBNull
        /// </summary>
        /// <param name="value">The value to check</param>
        /// <returns>Returns true if value passed is null or DBNull</returns>
        public static bool IsNullorDBNull(float value)
        {
            return IsNullorDBNull((object)value);
        }

        /// <summary>
        /// Determines if a passed value is null or DBNull
        /// </summary>
        /// <param name="value">The value to check</param>
        /// <returns>Returns true if value passed is null or DBNull</returns>
        public static bool IsNullorDBNull(bool value)
        {
            return IsNullorDBNull((object)value);
        }

        /// <summary>
        /// Determines if a passed value is null or dbnull
        /// </summary>
        /// <param name="value">The value to check</param>
        /// <returns>Returns true if value passed is null or empty</returns>
        public static bool IsNullorEmpty(string value)
        {
            return string.IsNullOrEmpty(value);
        }

        /// <summary>
        ///  Determines if a passed text value is true or false
        /// </summary>
        /// <param name="booleanText">string value to check</param>
        /// <returns>True if passed string is a boolean value</returns>
        public static bool IsBoolean(string booleanText)
        {
            bool resultValue = false;
            if (!IsNullorDBNull(booleanText))
            {
                // must be textual False or True
                if (booleanText.ToUpper() == "YES" || booleanText.ToUpper() == "ON")
                {
                    resultValue = true;
                }
                else
                {
                    bool retResult;
                    resultValue = bool.TryParse(booleanText, out retResult);
                }
            }

            return resultValue;
        }

        /// <summary>
        ///  Determines if a passed text value is a date
        /// </summary>
        /// <param name="dateText">string value to check</param>
        /// <returns>True if passed string is a date</returns>
        public static bool IsDate(string dateText)
        {
            bool resultValue = false;

            if (!IsNullorEmpty(dateText))
            {
                DateTime retResult;
                resultValue = DateTime.TryParse(dateText, out retResult);
            }

            return resultValue;
        }

        /// <summary>
        ///  Determines if a passed text value is a decimal value
        /// </summary>
        /// <param name="decimalText">string value to check</param>
        /// <returns>True if passed text value is a decimal</returns>
        public static bool IsDecimal(string decimalText)
        {
            bool resultValue = false;
            if (!IsNullorDBNull(decimalText))
            {
                decimal retResult;
                resultValue = decimal.TryParse(decimalText, out retResult);
            }

            return resultValue;
        }

        /// <summary>
        ///  Determines if a passed text value is an integer value
        /// </summary>
        /// <param name="numberText">string value to check</param>
        /// <returns>True if passed text value is an integer</returns>
        public static bool IsInteger(string numberText)
        {
            bool resultValue = false;
            if (!IsNullorDBNull(numberText))
            {
                int retResult;
                resultValue = int.TryParse(numberText, out retResult);
            }

            return resultValue;
        }

        /// <summary>
        ///  Determines if a passed text value is a long integer value
        /// </summary>
        /// <param name="numberText">string value to check</param>
        /// <returns>True if passed text value is a long integer</returns>
        public static bool IsLong(string numberText)
        {
            bool resultValue = false;
            if (!IsNullorDBNull(numberText))
            {
                long retResult;
                resultValue = long.TryParse(numberText, out retResult);
            }

            return resultValue;
        }

        /// <summary>
        ///  Determines if a passed text value is alphanumeric
        /// </summary>
        /// <param name="stringText">string value to check</param>
        /// <returns>True if passed string contains alphanumeric text</returns>
        public static bool IsAlphaNumeric(string stringText)
        {
            bool resultValue = false;

            if (!IsNullorDBNull(stringText))
            {
                Regex regex = new Regex("[^0-9a-zA-Z-.!_&? ]", RegexOptions.None);
                resultValue = !regex.Match(stringText).Success;
            }

            return resultValue;
        }

        /// <summary>
        ///  Determines if a passed text value is numeric
        /// </summary>
        /// <param name="value">string value to check</param>
        /// <returns>True if passed text value is numeric</returns>
        public static bool IsNumeric(object value)
        {
            bool resultValue = false;
            double retNum;
            resultValue = Double.TryParse(Convert.ToString(value), System.Globalization.NumberStyles.Any, System.Globalization.NumberFormatInfo.InvariantInfo, out retNum);
            return resultValue;
        }

        /// <summary>
        ///  Returns true if a passed string is considered an IP address
        /// </summary>
        /// <param name="address">string to parse</param>
        /// <returns>true if an ip address</returns>
        public static bool IsIPv4(string address)
        {
            bool resultValue = false;
            string[] octets = address.Split('.');
            if (octets.Length == 3)
            {
                resultValue = true;

                foreach (string octet in octets)
                {
                    if (!IsNumeric(octet))
                    {
                        resultValue = false;
                        break;
                    }
                }
            }

            return resultValue;
        }
        
        /// <summary>
        ///  Ensures a passed value is a string value
        /// </summary>
        /// <param name="value">The value to convert to a string</param>
        /// <returns>Returns a string variant of the passed value, string.Empty if passed value was null or DBNull</returns>
        public static string FixString(object value)
        {
            return FixString(value, string.Empty);
        }

        /// <summary>
        ///  Ensures a passed value is a string value
        /// </summary>
        /// <param name="value">The value to convert to a string</param>
        /// <param name="defaultValue">A default value to return if passed value is not string</param>
        /// <returns>Returns a string variant of the passed value, defaultValue if passed value was null or DBNull</returns>
        public static string FixString(object value, string defaultValue)
        {
            string resultValue = defaultValue;

            if (!IsNullorDBNull(value))
            {
                resultValue = Convert.ToString(value);
            }

            return resultValue;
        }

        /// <summary>
        ///  Ensures a passed value is an integer value
        /// </summary>
        /// <param name="value">the value to convert to an integer</param>
        /// <returns>returns an integer variant of the passed value, 0 if passed value is not an integer</returns>
        public static int FixInteger(object value)
        {
            return FixInteger(value, 0);
        }

        /// <summary>
        ///  Ensures a passed value is an integer value
        /// </summary>
        /// <param name="value">the value to convert to an integer</param>
        /// <param name="defaultValue">A default value to return if passed value is not integer</param>
        /// <returns>returns an integer variant of the passed value, defaultValue if passed value is not an integer</returns>
        public static int FixInteger(object value, int defaultValue)
        {
            int resultValue = defaultValue;

            if (!IsNullorDBNull(value) ? IsInteger(value.ToString()) : false)
            {
                resultValue = Convert.ToInt32(value);
            }

            return resultValue;
        }

        /// <summary>
        ///  Ensures a passed value is a boolean value
        /// </summary>
        /// <param name="value">the value to convert to a boolean</param>
        /// <returns>returns a boolean variant of the passed value, false if passed value is not an integer</returns>
        public static bool FixBoolean(object value)
        {
            return FixBoolean(value, false);
        }

        /// <summary>
        ///  Ensures a passed value is a boolean value
        /// </summary>
        /// <param name="value">the value to convert to a boolean</param>
        /// <param name="defaultValue">A default value to return if passed value is not boolean</param>
        /// <returns>returns a boolean variant of the passed value, defaultValue if passed value is not an integer</returns>
        public static bool FixBoolean(object value, bool defaultValue)
        {
            bool resultValue = defaultValue;

            if (!IsNullorDBNull(value))
            {
                if (IsNumeric(value))
                {
                    resultValue = FixInteger(value) > 0;
                }
                else
                {
                    if (IsBoolean(value.ToString()))
                    {
                        resultValue = Convert.ToBoolean(value);
                    }
                }
            }

            return resultValue;
        }

        /// <summary>
        ///  Ensures a passed value is a boolean value
        /// </summary>
        /// <param name="value">the value to convert to a boolean</param>
        /// <param name="defaultValue">A default value to return if passed value is not boolean</param>
        /// <returns>returns a boolean variant of the passed value, defaultValue if passed value is not an integer</returns>
        public static bool FixBoolean(object value, int defaultValue)
        {
            return FixBoolean(value, (defaultValue != 0));
        }

        /// <summary>
        ///  Ensures a passed value is a date value
        /// </summary>
        /// <param name="value">the value to convert to a datetime</param>
        /// <returns>returns a datetime variant of the passed value, DateTime.Now if passed value is not a date</returns>
        public static DateTime FixDateTime(object value)
        {
            return FixDateTime(value, DateTime.Now);
        }
        
        /// <summary>
        ///  Ensures a passed value is a date value
        /// </summary>
        /// <param name="value">the value to convert to a datetime</param>
        /// <param name="defaultValue">A default value to return if passed value is not a date</param>
        /// <returns>returns a datetime variant of the passed value, defaultValue if passed value is not an date</returns>
        public static DateTime FixDateTime(object value, DateTime defaultValue)
        {
            DateTime resultValue = defaultValue;

            if (IsDate(value.ToString()))
            {
                resultValue = Convert.ToDateTime(value);
            }

            return resultValue;
        }
       
        /// <summary>
        ///  Ensures a passed value is a decimal value
        /// </summary>
        /// <param name="value">the value to convert to a decimal</param>
        /// <returns>returns a decimal variant of the passed value, 0 if passed value is not an decimal</returns>
        public static decimal FixDecimal(object value)
        {
            return FixDecimal(value, 0);
        }
        
        /// <summary>
        ///  Ensures a passed value is a decimal value
        /// </summary>
        /// <param name="value">the value to convert to a decimal</param>
        /// <param name="defaultValue">A default value to return if passed value is not a decimal</param>
        /// <returns>returns a decimal variant of the passed value, defaultValue if passed value is not an decimal</returns>
        public static decimal FixDecimal(object value, decimal defaultValue)
        {
            decimal resultValue = defaultValue;

            if (IsDecimal(value.ToString()))
            {
                resultValue = Convert.ToDecimal(value);
            }

            return resultValue;
        }
       
        /// <summary>
        ///  Ensures a passed value is a long integer value
        /// </summary>
        /// <param name="value">the value to convert to a long</param>
        /// <returns>returns a long variant of the passed value, 0 if passed value is not a long</returns>
        public static long FixLong(object value)
        {
            return FixLong(value, 0);
        }
        
        /// <summary>
        ///  Ensures a passed value is a long integer value
        /// </summary>
        /// <param name="value">the value to convert to a long</param>
        /// <param name="defaultValue">A default value to return if passed value is not a long</param>
        /// <returns>returns a long variant of the passed value, defaultValue if passed value is not a long</returns>
        public static long FixLong(object value, long defaultValue)
        {
            long resultValue = defaultValue;

            if (IsLong(value.ToString()))
            {
                resultValue = Convert.ToInt64(value);
            }

            return resultValue;
        }
        #endregion
    }
}
